﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SdmxMl.Structure;
using SdmxMl.Common;
using SdmxMl.Excel;

namespace SasPlugIn.Table
{
    class CodelistArtefactTable : BaseSasTable
    {
        /// <summary>The artefact to transform in SAS instructions for table creation</summary>
        private CodeListType clt;

        /// <summary>
        /// C'tor for generation of a SAS table holding codelists artefact Information
        /// </summary>
        /// <param name="codelistArtefact">an object of Artefact type</param>
        /// <param name="anInv">inventory of selected annotations to place in table</param>
        /// <param name="prefix">Prefix for sas table</param>
        public CodelistArtefactTable(CodeListType codelistArtefact, AnnotationInventory anInv, string prefix)
            : base(codelistArtefact, "", prefix) 
        {
            clt = codelistArtefact;
            anInventory = anInv;
            header.Name = DefaultTableName(clt);
            FillHeader();
        }

        /// <summary>
        /// C'tor for generation of a SAS table holding codelists artefact Information
        /// </summary>
        /// <param name="codelistArtefact">an object of Artefact type</param>
        /// <param name="anInv">inventory of selected annotations to place in table</param>
        /// <param name="tableName">Name of Sas table</param>
        /// <param name="prefix">Prefix for sas table</param>
        public CodelistArtefactTable(CodeListType codelistArtefact, AnnotationInventory anInv, string tableName, string prefix)
            : base(codelistArtefact, tableName, prefix)
        {
            clt = codelistArtefact;
            anInventory = anInv;
            FillHeader();
        }

        public static string DefaultTableName(CodeListType clt)
        {
            return clt.Id.StartsWith("CL_") ? clt.Id.Substring(3) : clt.Id;
        }

        /// <summary>
        /// Fill Header columns according to artefact attributes
        /// </summary>
        protected override void FillHeader()
        {
            //sb.Append("(Code char(10), Parent char(10), Level char(2), ");
            //foreach (string lg in LangSupport.SupportedLanguages)
            //    sb.Append("Name_").Append(lg).Append(" char(120), ");

            //foreach (string lg in LangSupport.SupportedLanguages)
            //    sb.Append("Desc_").Append(lg).Append(" char(2000), ");

            //sb.Append("ValidFrom char(10), ValidTo char(10), ");

            // TODO: Add ctor giving TFT
            clt = artefact as CodeListType;
            TextFormatType tft = clt.GetDefaultTextFormat();
            TextFormatType tftLevel = new TextFormatType();
            tftLevel.TextType = TextTypeType.Integer;
            tftLevel.maxLength = "2";

            header.Add(new HeaderColumn(CODE_COL_NAME, tft));
            header.Add(new HeaderColumn(PARENT_COL_NAME, tft));
            header.Add(new HeaderColumn(LEVEL_COL_NAME, tftLevel));

            foreach (string lg in LangSupport.SupportedLanguages)
                header.Add(new HeaderColumn(INTERNATIONALIZED_NAME_PREFIX + lg, NAME_DEFAULT_LEN));

            foreach (string lg in LangSupport.SupportedLanguages)
                header.Add(new HeaderColumn(INTERNATIONALIZED_DESCR_PREFIX + lg, DESCRIPTION_DEFAULT_LEN));

            //header.Add(new HeaderColumn("ValidFrom", 10));
            //header.Add(new HeaderColumn("ValidTo", 10));

            // here Annotations selected
            GenAnnotationHeader();
        }

        protected override void GenerateDataRows(StringBuilder sb)
        {
            foreach (CodeType c in clt.CodeList)
            {
                List<string> rowValues = PrepareRowDatas(c);
                // Create instruction
                header.GenerateInsertTableInstructions(sb, rowValues.AsReadOnly());
            }
        }

        protected override List<string> PrepareRowDatas(object o)
        {
            CodeType c = o as CodeType;

            // Prepare row value list
            List<string> rowValues = new List<string>(header.Columns.Count);
            rowValues.Add(c.Id);
            rowValues.Add(c.Parent);
            rowValues.Add(GetLevelOfCode(clt, c.Id).ToString());

            foreach (string lg in LangSupport.SupportedLanguages)
            {
                rowValues.Add(c.Name.GetForLanguage(lg));
            }

            foreach (string lg in LangSupport.SupportedLanguages)
            {
                rowValues.Add(c.Description.GetForLanguage(lg));
            }

            //rowValues.Add(artefact.ValidFrom);
            //rowValues.Add(artefact.ValidTo);

            // Annotations
            AddAnnotations(rowValues, c.AnnotationList);

            return rowValues;
        }

        private int GetLevelOfCode(CodeListType clt, string code)
        {
            int level = 0;
            CodeType c = clt.CodeList.LocateItem(code) as CodeType;
            do
            {
                if (c != null)
                {
                    ++level;
                    c = clt.CodeList.LocateItem(c.Parent) as CodeType;
                }
            } while (c != null);

            return level;
        }

    }
}
